#include <unistd.h>
#include <getopt.h>

#include <memory>
#include <vector>
#include <string>
#include <stdexcept>

#include "string-util.h"
#include "sym-name-table.h"
#include "sym-find-print.h"
#include "log-util.h"

using std::vector;
using std::shared_ptr;
using std::string;
using std::runtime_error;

void sym_find_print_help()
{
     string help_doc =
"sym [find] OPTIONS OUTPUT-OPT LANGUAGE-OPT\n"
"OPTIONS 可取值有:\n"
"-h;输出当前帮助文档\n"
"-L LANGUAGE;指定符号所属语言;可以指定多个 -L 选项;如: -LC -LC++\n"
"LANGUAGE-OPT;指定了如何确定 1 个符号;取决于所使用的语言,具体如下:\n";
     const auto &langs_vec = SymNameTable::supportLanguages();
     for (const auto &lang_name : langs_vec) {
         SymNameTable *lang_symname_table = SymNameTable::instance(lang_name);
         if (lang_symname_table == NULL)
             throw runtime_error(format("无法创建语言 %s 的实例!",lang_name.c_str()));
         help_doc += lang_name;
         help_doc.append(1,';');
         help_doc += lang_symname_table->help();
         help_doc.append(1,'\n');
     }
    help_doc +=
"OUTPUT-OPT;指定了如何输出搜索结果\n"
"-F|--full;显示符号介绍的全部内容,默认情况下只会显示一行";
    puts(help_doc.c_str());
    return ;
}


int sym_find_main(int argc,char **argv)
{
    SymFindPrint printer;
    printer.init(argc,argv);

    vector<SymNameTable*> name_table_vec;
    bool has_L_opt = false;

    int getopt_ret;
    optind = 0;
    opterr = 0;
    while ((getopt_ret = getopt(argc,argv,"-hL:")) != -1) {
        switch (getopt_ret) {
        case 'h': {
            sym_find_print_help();
            return 0;
        }   break;
        case 'L': {
            has_L_opt = true;
            SymNameTable *name_table = SymNameTable::instance(optarg);
            if (name_table != NULL)
                name_table_vec.push_back(name_table);
        }   break;
        default:
            break;
        }
    }

    if (!has_L_opt) {
        const auto &lang_name_vec = SymNameTable::supportLanguages();
        for (const auto &lang_name : lang_name_vec) {
            SymNameTable *name_table = SymNameTable::instance(lang_name);
            if (name_table != NULL)
                name_table_vec.push_back(name_table);
        }
    }
    if (name_table_vec.empty()) {
        LOGE("没有可用的语言!");
        return 1;
    }

    do {
        SymNameTable *name_table = name_table_vec.back();
        shared_ptr<SymName> symname = name_table->getSymName(argc,argv);
        const auto &find_results = name_table->find(symname);
        for (const auto &result : find_results)
            printer.print(result.first,result.second);
        name_table_vec.pop_back();
    } while (!name_table_vec.empty());

    return 0;
}


